package cn.imvc.app.models;

import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.alibaba.druid.util.StringUtils;

import cn.imvc.app.commons.SystemConfig;
import cn.imvc.app.domains.Constants;
import cn.imvc.app.domains.FundFlowType;
import cn.imvc.app.entities.Commission;
import cn.imvc.app.entities.DealerApply;
import cn.imvc.app.entities.Member;
import cn.imvc.app.repositories.CommissionRepository;
import cn.imvc.core.ICache;
import cn.imvc.data.domain.ViewRequest;

@Service
public class CommissionModelImpl implements CommissionModel {

	@Autowired
	private CommissionRepository commissionRepository;

	@Autowired
	DealerApplyModel dealerApplyModel;

	@Autowired
	MemberModel memberModel;

	@Autowired
	FundFlowModel fundFlowModel;

	@Autowired
	AccountModel accountModel;

	@Autowired
	OrderModel orderModel;

	@Autowired
	ICache cache;

	@Autowired
	SystemConfig systemConfig;

	public Commission get(int id) {
		return commissionRepository.findOne(id);
	}

	public Page<Commission> find(ViewRequest viewRequest) {
		return (Page<Commission>) commissionRepository.findAll();
	}

	public Commission save(Commission commission) {

		Commission commission2 = commissionRepository.saveAndFlush(commission);

		return commission2;
	}

	public Commission update(Commission newCommission) {
		Commission loadCommission = get(newCommission.getId());
		BeanUtils.copyProperties(newCommission, loadCommission, new String[] { "id" });

		return commissionRepository.saveAndFlush(loadCommission);
	}

	public void delete(int id) {
		commissionRepository.delete(id);

	}

	public void deleteBatch(int[] ids) {

		for (int id : ids) {
			delete(id);
		}

	}

	public void addCommission(Member member, Byte type, Integer referId) {
		String referCode = null;
		Integer money = 0;
		Byte fundFlowType = 0;
		if (type == 1) {

		}
		if (type == 2) {
			DealerApply dealerApply = dealerApplyModel.get(referId);
			money = dealerApply.getJoinMoney();
			referCode = dealerApply.getCode();
			fundFlowType = FundFlowType.JoinCommissions.getValue();
		}
		Commission firstCommission = new Commission();
		Member parent = member.getParent();
		if (parent != null) {
			if (money * systemConfig.firstLevelPercent / 100 > 0) {

				firstCommission.setMember(parent);
				firstCommission.setAccount(parent.getAccount());
				firstCommission.setMoney(money * systemConfig.firstLevelPercent / 100);
				firstCommission.setRate(systemConfig.firstLevelPercent);
				firstCommission.setFromMember(member);
				firstCommission.setCreatedAt(new Date());
				firstCommission.setReferId(referId);
				firstCommission.setReferCode(referCode);
				firstCommission.setType(type);
				save(firstCommission);
				fundFlowModel.addFundFlow(parent, firstCommission.getMoney(), referCode, fundFlowType,member);
				accountModel.retrySaveAccount(parent.getAccount().getId(), firstCommission.getMoney(),
						firstCommission.getMoney(), 0);
			}
			Commission secondCommission = new Commission();
			Member grandpa = parent.getParent();
			if (grandpa != null) {
				if (money * systemConfig.secondLevelPercent / 100 > 0) {

					secondCommission.setMember(grandpa);
					secondCommission.setAccount(grandpa.getAccount());
					secondCommission.setMoney(money * systemConfig.secondLevelPercent / 100);
					secondCommission.setRate(systemConfig.secondLevelPercent);
					secondCommission.setFromMember(member);
					secondCommission.setCreatedAt(new Date());
					secondCommission.setReferId(referId);
					secondCommission.setReferCode(referCode);
					secondCommission.setType(type);
					save(secondCommission);
					fundFlowModel.addFundFlow(grandpa, secondCommission.getMoney(), referCode, fundFlowType,member);
					accountModel.retrySaveAccount(grandpa.getAccount().getId(), secondCommission.getMoney(),
							secondCommission.getMoney(), 0);
				}
			}

		}
	}

	public void addPointsCommission(Member member, Byte type, Integer money, Member formMember) {
		Byte fundFlowType = 0;
		if (type == 20) {
			fundFlowType = FundFlowType.PointsRecommend.getValue();
			Commission commission = new Commission();
			commission.setMember(member);
			commission.setAccount(member.getAccount());
			commission.setMoney(money);
			commission.setRate(null);
			commission.setFromMember(formMember);
			commission.setCreatedAt(new Date());
			commission.setReferId(null);
			commission.setReferCode(null);
			commission.setType(type);
			save(commission);
			fundFlowModel.addFundFlow(member, commission.getMoney(), null, fundFlowType, formMember);
			accountModel.retrySaveAccount(member.getAccount().getId(), 0, 0, money);
		}
	}

	public Page<Object[]> findPageTeamDetail(Member member, Integer page, String type) {
		PageRequest pageRequest = new PageRequest(page, Constants.TEAM_PAGE_SIZE, null);
		if("0".equals(type) || "1".equals(type)){
			return commissionRepository.findAllSql(bulidSql(member, type), pageRequest);
		} else {
			Page<Object[]> result = findDealerMemberIds(member, pageRequest);
			if(result != null){
				Iterator<Object[]> ite = result.iterator();
				while(ite.hasNext()) {
					Object[] dealer = ite.next();
					List<Object[]> sum = findDealerMoney(dealer[5].toString());
					if(sum != null && sum.size() > 0){
						String objs = String.valueOf(sum.get(0));
						if(!StringUtils.isEmpty(objs)){
							dealer[0] = objs;
						} else {
							dealer[0] = 0;
						}
					} else {
						dealer[0] = 0;
					}
				}
				return result;
			} else {
				return null;
			}
		}
	}
	
	private Page<Object[]> findDealerMemberIds(Member member, Pageable page) {
		return commissionRepository.findAllSql("SELECT '' money1,'' money2 ,m.id, m.`name`, m.loginname, m.guid FROM member m INNER JOIN dealer d ON m.id=d.memberId WHERE  m.guid LIKE '" + member.getGuid() + ",%' and d.dealerLevelId=2", page);
	}
	
	private List<Object[]> findDealerMoney(String guid) {
		// 钱
		return commissionRepository.findAllSql("SELECT ifnull(SUM(t.money),0)*0.01 FROM (SELECT ifnull((SELECT SUM(resultAmount - freightAmount - refundAmount) FROM orders WHERE memberId=m.id),0) as money"
				+ " FROM member m WHERE m.guid LIKE '" + guid + ",%' and !(m.guid regexp concat('',(SELECT GROUP_CONCAT(m2.id SEPARATOR '|') FROM member m2 INNER JOIN dealer d2"
				+ " ON m2.id=d2.memberId WHERE  m2.guid LIKE '" + guid + ",%'  and d2.dealerLevelId=2)))  GROUP BY m.id ) as t");
	}

	public Page<Object[]> findPageTeamDetail(Member member, Pageable page, String type) {
		if("0".equals(type) || "1".equals(type)){
			return commissionRepository.findAllSql(bulidSql(member, type), page);
		} else {
			Page<Object[]> result = findDealerMemberIds(member, page);
			if(result != null){
				Iterator<Object[]> ite = result.iterator();
				while(ite.hasNext()) {
					Object[] dealer = ite.next();
					List<Object[]> sum = findDealerMoney(dealer[5].toString());
					if(sum != null && sum.size() > 0){
						String objs = String.valueOf(sum.get(0));
						if(!StringUtils.isEmpty(objs)){
							dealer[0] = objs;
						} else {
							dealer[0] = 0;
						}
					} else {
						dealer[0] = 0;
					}
				}
				return result;
			} else {
				return null;
			}
		}
	}

	public List<Object[]> findCommPointsByMember(Member member) {
		return commissionRepository.findAllSql("select sum(c.money) from commission c where c.memberId=" + member.getId() + " and type in(10,11,12,20)");
	}
	
	private String bulidSql(Member member, String type) {
		StringBuffer sb = new StringBuffer();
		if ("0".equals(type)) {
			// 积分
//			sb.append("SELECT ifnull((SELECT SUM(resultAmount - freightAmount - refundAmount) FROM orders WHERE memberId=m.id and state >= 60),0) as money ,ifnull(SUM(c.money),0) as points,m.id, m.`name`, m.loginname, m.guid"
//					+ " FROM member m LEFT JOIN commission c ON c.memberId=" + member.getId() + " and m.id=c.fromMemberId and c.type=12 WHERE m.parentId=" + member.getId() + " GROUP BY m.id ");
			sb.append("SELECT ifnull((SELECT SUM(resultAmount - freightAmount - refundAmount) FROM orders WHERE memberId = m.id AND state >= 60), 0) AS money,"
					+ " ifnull(SUM(c.money), 0) AS points, m.id, m.`name`, m.loginname, m.guid, l.`level` FROM member m LEFT JOIN commission c ON c.memberId = " + member.getId()
					+ " AND m.id = c.fromMemberId AND c.type = 12 left join dealer d on m.id = d.memberId left JOIN dealer_level l on d.dealerLevelId = l.id"
					+ " WHERE m.parentId = " + member.getId() + " GROUP BY m.id order by l.`level` desc");
		} else if ("1".equals(type)) {
			// 钱
//			sb.append("SELECT ifnull((SELECT SUM(resultAmount - freightAmount - refundAmount) FROM orders WHERE memberId=m.id and state >= 60),0)*0.01 as money,'0' money2,m.id, m.`name`, m.loginname, m.guid"
//					+ " FROM member m  WHERE m.guid LIKE '" + member.getGuid() + ",%' and !(m.guid regexp concat('^', ifnull((SELECT GROUP_CONCAT(m2.id SEPARATOR '|') FROM member m2"
//					+ " INNER JOIN dealer d2 ON m2.id=d2.memberId WHERE  m2.guid LIKE '" + member.getGuid() + ",%' and d2.dealerLevelId=2),'$')))  GROUP BY m.id");
			sb.append("SELECT ifnull((SELECT SUM(resultAmount - freightAmount - refundAmount) FROM orders WHERE memberId = m.id AND state >= 60), 0) * 0.01 AS money, '0' money2, m.id, m.`name`, m.loginname, m.guid, l.`level`"
					+ "FROM member m left join dealer d on m.id = d.memberId left join dealer_level l on l.id = d.dealerLevelId WHERE m.guid LIKE '" + member.getGuid() + ",%' GROUP BY m.id order by l.`level` desc");
		}
		return sb.toString();
	}
	
	public StringBuffer getMemberStrForDealer(Member member) {
		StringBuffer str = new StringBuffer();
		List<Member> memberList = memberModel.findByParent(member);
		for (Member tmpMember : memberList) {
			if (tmpMember.getDealer().getDealerLevel().getType() == 1) {
				str.append("," + tmpMember.getId());
				str.append(getMemberStrForDealer(tmpMember));
			}
		}
		return str;
	}

	public Page<Commission> findOrderPointsByMember(Member member, byte type, Pageable page) {
		return commissionRepository.findByMemberAndType(member, type, page);
	}

}
